import java.util.*;   
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;   
  
   
   
class GameCanvas extends Canvas implements Runnable, CommandListener  {   
/*  OptionsCanvas opt; */   
  int delay=50;     //delay between two frames   
  int speed=1000/(delay-10);   
  long startTime;   
  int seconds;   
  Display display;   
  Image offscreen;   
  Random rnd;   
  SnakeMidlet midlet;   
  int rd=255, gr=0, bl=0;   
  public int sw, sh;   
  int[] snake_x;   
  int[] snake_y;   
  int n_snake=8;      // current size of snake   
  int snakewidth=6; // snake will be 6 pixels wide   
  int growth_rate=3;   
  int x_max, y_max;   
  boolean first_run=false;   
  int game_state=1;         // 1 - running   
                            // 2 - menu (options)   
     
  int apple_x, apple_y;   
     
  char dir='u';   
  int score=0;   
    
    static final Command exitCommand = new Command ("Exit", Command.EXIT, 2);   
    static final Command menuCommand = new Command ("Menu", Command.ITEM, 1);   
     
   
      
       
  GameCanvas (Display display, SnakeMidlet caller) {   
    /*opt = new OptionsCanvas(display,this); */   
    rnd = new Random();   
    this.setFullScreenMode(true);   
    midlet = caller;   
    /* Set the high-level commands */   
    this.addCommand (exitCommand);   
    this.addCommand (menuCommand);   
    this.setCommandListener(this);   
       
       
    sw=getWidth();   
    sh=getHeight();   
    x_max=sw/snakewidth;   
    y_max=sh/snakewidth;   
       
    apple_x=Math.abs((rnd.nextInt())%x_max);   
    apple_y=Math.abs((rnd.nextInt())%y_max);   
       
    snake_x=new int[sw*sh/snakewidth/snakewidth];   
    snake_y=new int[sw*sh/snakewidth/snakewidth];   
       
       
    int i;   
    for(i=0;i<n_snake;i++) {   
        snake_x[i]=x_max/2;   
        snake_y[i]=i;   
    }   
               
    this.display = display; // this -> the current class   
    this.seconds = seconds;   
    
    if (!isDoubleBuffered () && false) {
          offscreen = Image.createImage (sw, sh);
      }   
    
    startTime = System.currentTimeMillis ();   
  }   
    
  public void paint (Graphics g) {   
       
    // if offscreen is not present (auto double buffer), use orignal screen   
    Graphics g2 = offscreen == null    
      ? g   
      : offscreen.getGraphics ();   
         
    // clear the screen   
    g2.setColor (0, 0, 255);   
    g2.fillRect (0, 0, sw, sh);   
    
       
    //draw the apple   
    g2.setColor(255,0,0);   
    g2.fillArc(apple_x*snakewidth,apple_y*snakewidth,   
                snakewidth, snakewidth, 0, 360);   
    g2.setColor(255,100,10);   
    g2.fillArc(apple_x*snakewidth+1,apple_y*snakewidth+2,   
                2, 2, 0, 360);   
    g2.setColor(50,255,10);   
    g2.fillRect(apple_x*snakewidth+snakewidth/2,apple_y*snakewidth,   
                1, 3);   
       
       
       
    // draw the snake   
   
    int i;   
    for(i=0;i<n_snake;i++) {   
        g2.setColor(200,180,20);   
        g2.fillRect(snake_x[i]*snakewidth,snake_y[i]*snakewidth,   
                snakewidth, snakewidth);   
        g2.setColor(255,255,0);           
        g2.fillRect(snake_x[i]*snakewidth+1,snake_y[i]*snakewidth+1,   
                snakewidth-1, snakewidth-1);   
    }   
    display.callSerially (this);   
       
   
    
    // copy the buffer to the screen   
    if (offscreen != null) {
          g.drawImage (offscreen, 0, 0, Graphics.TOP | Graphics.RIGHT);
      }    
  }   
   
    /* Handle the High Level Keys*/   
    public void commandAction (Command c, Displayable d) {   
      if(c==exitCommand) {   
          midlet.destroyApp(false);   
      }   
      if(c==menuCommand) {   
          speed=1000/(delay-10);   
          game_state=2;   
      }   
    }          
     
    /* Low level commands*/   
    public void keyPressed (int keyCode) {   
        switch(keyCode) {   
            case KEY_NUM2:   
                if(dir!='d') {
            dir='u';
        }   
                break;   
            case KEY_NUM8:                   
                if(dir!='u') {
            dir='d';
        }   
                break;   
            case KEY_NUM6:                                   
                if(dir!='l') {
            dir='r';
        }   
                break;   
            case KEY_NUM4:   
                if(dir!='r') {
            dir='l';
        }   
                break;   
        }   
        switch(getGameAction(keyCode)) {   
            case UP:   
                if(dir!='d') {
            dir='u';
        }   
                break;   
            case DOWN:   
                if(dir!='u') {
            dir='d';
        }   
                break;   
            case RIGHT:   
                if(dir!='l') {
            dir='r';
        }   
                break;   
            case LEFT:                   
                if(dir!='r') {
            dir='l';
        }   
                break;   
        }   
        //repaint ();   
    }   
   
     
  public void run () {   
    int i;   
    i = (int) System.currentTimeMillis ();   
    if(!first_run) {   
        startTime=i;   
        first_run=true;   
    }   
   
    if(Math.abs(i-startTime)>=delay) {   
        startTime=startTime+delay; // = i;   
   
        // shift the pieces forward   
        for(i=n_snake-1;i>0;i--) {   
            snake_x[i]=snake_x[i-1];   
            snake_y[i]=snake_y[i-1];   
        }   
   
        // calculate the new piece (depending on the direction)   
        switch(dir) {   
            case 'd':   
                snake_y[0]=snake_y[0]+1;   
                if(snake_y[0]==y_max) {
            snake_y[0]=0;
        }   
                break;   
   
            case 'u':   
                if(snake_y[0]==0) {
            snake_y[0]=y_max-1;
        }   
                else {
            snake_y[0]=snake_y[0]-1;
        }   
                break;   
   
            case 'r':   
                snake_x[0]=snake_x[0]+1;   
                if(snake_x[0]==x_max) {
            snake_x[0]=0;
        }   
                break;   
   
            case 'l':   
                if(snake_x[0]==0) {
            snake_x[0]=x_max-1;
        }   
                else {
            snake_x[0]=snake_x[0]-1;
        }   
                break;   
   
        }   
   
        /* Check if the snake is eating itself */   
        for(i=1;i<n_snake;i++) {   
            if(snake_x[i]==snake_x[0]&&snake_y[i]==snake_y[0]) {   
                // GAME OVER   
                Alert alert = new Alert ("Game Over");   
                alert.setTimeout (Alert.FOREVER);   
                alert.setString("Score: "+java.lang.String.valueOf(score));   
                display.setCurrent (alert);   
                   
                n_snake=8;   
                for(i=0;i<n_snake;i++) {   
                    snake_x[i]=x_max/2;   
                    snake_y[i]=i;   
                }             
                dir='u';   
                first_run=false;   
                score=0;   
            }   
        }   
           
           
        /* Check if an apple is eaten */   
        if(snake_x[0]==apple_x&&snake_y[0]==apple_y) {   
            for(i=n_snake;i<n_snake+growth_rate;i++) {   
                snake_x[i]=snake_x[0];   
                snake_y[i]=snake_y[0];   
            }   
                   
            n_snake+=growth_rate;   
            score+=9;   
            apple_x=Math.abs((rnd.nextInt())%x_max);   
            apple_y=Math.abs((rnd.nextInt())%y_max);   
        }   
           
        repaint();   
    }   // the outermost if ends here   
    else {   
        display.callSerially (this);   
    }   
  } //function run ends here   
}   // class GameCanvas ends here   
    
    
public class SnakeMidlet extends MIDlet {   
       
  public static Display display;   
  public void startApp () {   
    display = Display.getDisplay (this);   
    display.setCurrent (new GameCanvas (display, this));    
  }   
    
  public void pauseApp () {   
  }   
     
  public void destroyApp (boolean forced) {   
    this.notifyDestroyed();   
  }   
} 